package com.yc.testupload.controller;

import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.yc.testupload.util.DatabaseUtil;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 用于处理Word文档上传并返回七牛云URL的Servlet
 * 专门为素材库上传功能设计
 */
public class WordForMaterialUploadServlet extends HttpServlet {
    private static final Logger logger = LogManager.getLogger(WordForMaterialUploadServlet.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();

    // 本地临时文件保存路径
    private String uploadPath;

    // 七牛云配置（复用自FileUploadServlet）
    private static final String ACCESS_KEY = "vV_FGopUcLpPKwImUgDE8a2lCgTQjsdUqQmSpoa1";
    private static final String SECRET_KEY = "w94IZ6dV899KrEqofAFwkagn0SSeZPPEXgaTj3Jr";
    private static final String BUCKET_NAME = "project-yytimes";
    private static final String DOMAIN = "static.didaproject.com";

    @Override
    public void init() throws ServletException {
        super.init();
        // 初始化上传路径，使用与FileUploadServlet相同的路径逻辑
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        String dateDir = dateFormat.format(new Date());
        
        // 尝试获取webapp目录
        String webappPath = getServletContext().getRealPath("/");

        // 如果getRealPath返回null（例如在独立JAR运行模式下），使用当前工作目录
        if (webappPath == null) {
            webappPath = System.getProperty("user.dir") + File.separator;
        }

        // 确保webappPath以分隔符结尾
        if (!webappPath.endsWith(File.separator)) {
            webappPath += File.separator;
        }

        // 使用File.separator构建跨平台兼容的上传路径
        uploadPath = webappPath + "uploads" + File.separator + dateDir + File.separator;
        logger.info("WordForMaterialUploadServlet - 设置文件上传路径: {}", uploadPath);

        File uploadDir = new File(uploadPath);
        if (!uploadDir.exists()) {
            boolean created = uploadDir.mkdirs();
            logger.info("创建上传目录: {}, 结果: {}", uploadPath, created);
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        logger.info("接收到Word文档上传请求（用于素材库），请求ID: {}", request.getSession().getId());

        // 设置响应类型
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");

        try {
            // 获取上传的文件
            Part filePart = request.getPart("file");
            String title = request.getParameter("title") != null ? request.getParameter("title") : "未命名文档";

            if (filePart == null || filePart.getSize() == 0) {
                sendErrorResponse(response, "未接收到文件");
                return;
            }

            // 生成唯一的文件名
            String fileName = generateUniqueFileName(title, ".doc");

            // 保存临时文件
            String tempFilePath = saveTempFile(filePart, fileName);

            // 上传到七牛云
            String qiniuUrl = uploadToQiniuCloud(tempFilePath, fileName);

            // 删除临时文件
            Files.deleteIfExists(Paths.get(tempFilePath));

            if (qiniuUrl != null) {
                logger.info("Word文档上传成功，七牛云URL: {}", qiniuUrl);

                // 从session中获取用户ID
                Integer userId = (Integer) request.getSession().getAttribute("userId");
                logger.info("从会话中获取用户ID: {}, 请求ID: {}", userId, request.getSession().getId());
                if (userId == null) {
                    logger.warn("会话中未找到用户ID，无法将素材信息插入数据库，请求ID: {}", request.getSession().getId());
                } else {
                    // 将素材信息插入到数据库
                    logger.info("准备插入素材信息到数据库，请求ID: {}", request.getSession().getId());
                    insertMaterialToDatabase(userId, title, qiniuUrl);
                }

                sendSuccessResponse(response, qiniuUrl);
            } else {
                logger.error("Word文档上传到七牛云失败");
                sendErrorResponse(response, "文件上传到七牛云失败");
            }
        } catch (Exception e) {
            logger.error("处理Word文档上传时发生错误", e);
            sendErrorResponse(response, "服务器内部错误：" + e.getMessage());
        }
    }

    /**
     * 将素材信息插入到数据库
     */
    private void insertMaterialToDatabase(Integer userId, String title, String qiniuUrl) {
        logger.info("开始将素材信息插入数据库: 标题={}, 用户ID={}", title, userId);
        Connection conn = null;
        PreparedStatement pstmt = null;
        
        try {
            // 获取数据库连接
            conn = DatabaseUtil.getConnection();
            logger.info("已获取数据库连接");
            
            // 获取当前时间戳（秒）
            long currentTime = System.currentTimeMillis() / 1000;
            
            // 保存到wk_material表
            String sql = "INSERT INTO wk_material (title, content, user_id, add_time, edit_time, status) VALUES (?, ?, ?, ?, ?, ?)";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, title);
            pstmt.setString(2, qiniuUrl); // content存储七牛云文件地址
            pstmt.setInt(3, userId);
            pstmt.setLong(4, currentTime);
            pstmt.setLong(5, currentTime);
            pstmt.setInt(6, 1); // status，设为1（可用）
            
            int rowsAffected = pstmt.executeUpdate();
            logger.info("素材信息插入数据库成功，影响行数: {}", rowsAffected);
            
        } catch (SQLException e) {
            logger.error("将素材信息插入数据库失败: {}", e.getMessage(), e);
        } finally {
            // 关闭数据库资源
            if (pstmt != null) {
                try { pstmt.close(); } catch (SQLException e) { logger.error("关闭PreparedStatement失败", e); }
            }
            DatabaseUtil.closeConnection(conn);
        }
    }
    
    /**
     * 生成唯一的文件名
     */
    private String generateUniqueFileName(String title, String extension) {
        // 过滤文件名中的非法字符
        String safeTitle = title.replaceAll("[^a-zA-Z0-9_\u4e00-\u9fa5]", "_");

        // 生成时间戳和随机字符串
        long timestamp = System.currentTimeMillis();
        String randomStr = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 8);

        // 组合成最终的文件名
        return safeTitle + "_" + timestamp + "_" + randomStr + extension;
    }

    /**
     * 保存临时文件到服务器
     */
    private String saveTempFile(Part filePart, String fileName) throws IOException {
        // 创建日期目录
        String dateDir = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String saveDir = uploadPath + File.separator + dateDir;
        File dir = new File(saveDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        // 构建完整的文件路径
        String filePath = saveDir + File.separator + fileName;

        // 写入文件
        filePart.write(filePath);

        return filePath;
    }

    /**
     * 将文件上传到七牛云
     * 复用自FileUploadServlet的逻辑
     */
    private String uploadToQiniuCloud(String filePath, String fileName) {
        String qiniuUrl = null;

        try {
            // 构建七牛云配置，使用Zone.autoZone自动选择最优区域
            com.qiniu.storage.Configuration cfg = new com.qiniu.storage.Configuration(com.qiniu.common.Zone.autoZone());

            // 创建上传管理器
            com.qiniu.storage.UploadManager uploadManager = new com.qiniu.storage.UploadManager(cfg);

            // 获取文件扩展名
            String fileExt = fileName.substring(fileName.lastIndexOf("."));

            // 生成时间戳加随机字符串的文件名，符合用户要求的格式
            long timestamp = System.currentTimeMillis();
            String randomStr = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 10);
            String newFileName = timestamp + randomStr + fileExt;

            // 构建七牛云中的文件路径，使用wenku前缀
            String key = "wenku/" + newFileName;

            // 生成上传凭证
            com.qiniu.util.Auth auth = com.qiniu.util.Auth.create(ACCESS_KEY, SECRET_KEY);
            String upToken = auth.uploadToken(BUCKET_NAME, key);

            // 上传文件
            com.qiniu.http.Response response = uploadManager.put(filePath, key, upToken);

            // 构建文件的访问URL
            qiniuUrl = "https://" + DOMAIN + "/" + key;

            logger.info("文件已成功上传到七牛云，URL: {}", qiniuUrl);
        } catch (com.qiniu.common.QiniuException e) {
            logger.error("上传文件到七牛云失败: {}", e.getMessage());
            // 可以获取响应信息
            if (e.response != null) {
                logger.error("七牛云错误响应: {}", e.response.toString());
            }
        } catch (Exception e) {
            logger.error("上传文件到七牛云时发生异常: {}", e.getMessage());
        }

        return qiniuUrl;
    }

    /**
     * 发送成功响应
     */
    private void sendSuccessResponse(HttpServletResponse response, String qiniuUrl) throws IOException {
        PrintWriter out = response.getWriter();
        out.print(objectMapper.writeValueAsString(new UploadResult(true, "文件上传成功", qiniuUrl)));
        out.flush();
    }

    /**
     * 发送错误响应
     */
    private void sendErrorResponse(HttpServletResponse response, String message) throws IOException {
        PrintWriter out = response.getWriter();
        out.print(objectMapper.writeValueAsString(new UploadResult(false, message, null)));
        out.flush();
    }

    /**
     * 上传结果类
     */
    private static class UploadResult {
        private boolean success;
        private String message;
        private String qiniuUrl;

        public UploadResult(boolean success, String message, String qiniuUrl) {
            this.success = success;
            this.message = message;
            this.qiniuUrl = qiniuUrl;
        }

        public boolean isSuccess() {
            return success;
        }

        public void setSuccess(boolean success) {
            this.success = success;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

        public String getQiniuUrl() {
            return qiniuUrl;
        }

        public void setQiniuUrl(String qiniuUrl) {
            this.qiniuUrl = qiniuUrl;
        }
    }
}